<?php
/**
 * 新梭哈
 */
namespace app\chess;

Class NewPoker
{
    /**
     * 同花顺
     * @var integer
     */
    private $Flush = 9;

    /**
     * 炸弹
     * @var integer
     */
    private $Bomb = 8;

    /**
     * 葫芦
     * @var integer
     */
    private $Gourd = 7;

    /**
     * 同花
     * @var integer
     */
    private $WithColor = 6;

    /**
     * 顺子
     * @var integer
     */
    private $Straight = 5;

    /**
     * 三条
     * @var integer
     */
    private $Threefakind = 4;

    /**
     * 两对
     * @var integer
     */
    private $TwoPair = 3;

    /**
     * 一对
     * @var integer
     */
    private $OnePair = 2;

    /**
     * 散牌
     * @var integer
     */
    private $Single = 1;

    /**
     * 一副牌
     * 方块 梅花 红桃 黑桃
     * @var [type]
     */
    private $cards = [
        68, 48, 28, 8,  // 8
        69, 49, 29, 9,  // 9
        70, 50, 30, 10, // 10
        71, 51, 31, 11, // J
        72, 52, 32, 12, // Q
        73, 53, 33, 13, // K
        61, 41, 21, 1   // A
    ];

    /**
     * 一副牌矩阵
     * 方块 梅花 红桃 黑桃
     * @var [type]
     */
    private $cardsMatrix = [
        [68, 48, 28, 8],  // 8
        [69, 49, 29, 9],  // 9
        [70, 50, 30, 10], // 10
        [71, 51, 31, 11], // J
        [72, 52, 32, 12], // Q
        [73, 53, 33, 13], // K
        [61, 41, 21, 1]   // A
    ];

    /**
     * 牌型矩阵, 0->方块 1->梅花 2->红桃 3->黑桃
     * @var array
     */
    private $cardMatrix = [
        [0, 0, 0, 0], // 8
        [0, 0, 0, 0], // 9
        [0, 0, 0, 0], // 10
        [0, 0, 0, 0], // J
        [0, 0, 0, 0], // Q
        [0, 0, 0, 0], // K
        [0, 0, 0, 0], // A
    ];

    public function __construct()
    {}

    /**
     * 洗牌
     *
     * @return [type] [description]
     */
    public function doShuffle()
    {
        shuffle($this->cards);
        return $this->cards;
    }

    /**
     * 发牌
     *
     * @param  [type] $cards 剩余的牌堆
     * @return [type]        [description]
     */
    public function sendCard($cards)
    {
        // 牌堆没牌发牌错误
        if (count($cards) <= 0) {
            return false;
        }

        $card = array_pop($cards);
        return [
            'card'  => $card,
            'cards' => $cards
        ];
    }

    /**
     * 获取牌型矩阵
     *
     * @param  [type] $cards array
     * array(
     *     array(
     *         'card' => 1, // 牌
     *         'status' => false // 开牌状态
     *     ),
     *     ...
     * )
     * @return [type]        [description]
     */
    public function getCardsMatrix($cards)
    {
        $matrix = $this->cardMatrix;
        $cardMatrix = $this->cardsMatrix;

        foreach ($cards as $k1 => $v1) {
            foreach ($cardMatrix as $k2 => $v2) {
                foreach ($v2 as $k3 => $v3) {
                    if ($v1['card'] == $v3) {
                        $matrix[$k2][$k3] = 1;
                    }
                }
            }
        }

        return $matrix;
    }

    /**
     * 获取最后一张牌的矩阵
     *
     * @param  [type] $cards array
     * array(
     *     array(
     *         'card' => 1, // 牌
     *         'status' => false // 开牌状态
     *     ),
     *     ...
     * )
     * @return [type]        [description]
     */
    public function getLastCardMatrix($cards)
    {
        $newCards[0] = $cards[count($cards)-1];
        return $this->getCardsMatrix($newCards);
    }

    /**
     * 根据牌矩阵获取牌点数
     *
     * @param  [type] $card [description]
     * @return [type]       [description]
     */
    public function getCardCountByCardsMatrix($matrix)
    {
        $count = 0;
        foreach ($matrix as $k1 => $v1) {
            foreach ($v1 as $k2 => $v2) {
                if ($v2 === 1) {
                    $count += ($k1*4+1)+$k2;
                }
            }
        }
        return $count;
    }

    /**
     * 获取牌类型
     *
     * @return [type] [description]
     */
    public function getCardTypeAndNumber($matrix)
    {
        $result = [
            'type' => 0,
            'number' => $this->getCardCountByCardsMatrix($matrix)
        ];

        // 判定牌型
        if ($this->isFlush($matrix)) {
            $result['type'] = $this->Flush;
        } elseif ($this->isBomb($matrix)) {
            $result['type'] = $this->Bomb;
        } elseif ($this->isPairs($matrix) === 2) {
            $result['type'] = $this->TwoPair;
        } elseif ($this->isPairs($matrix) === 1 && $this->isThreefakind($matrix)) {
            $result['type'] = $this->Gourd;
        } elseif ($this->isPairs($matrix) === 1 && !$this->isThreefakind($matrix)) {
            $result['type'] = $this->OnePair;
        } elseif ($this->isPairs($matrix) === 0 && $this->isThreefakind($matrix)) {
            $result['type'] = $this->Threefakind;
        } elseif ($this->isWithColor($matrix)) {
            $result['type'] = $this->$WithColor;
        } elseif ($this->isStraight($matrix)) {
            $result['type'] = $this->Straight;
        } else {
            $result['type'] = $this->Single;
        }

        return $result;
    }

    /**
     * 判定同花顺
     *
     * @return boolean [description]
     */
    private function isFlush($matrix)
    {
        $fisrt = [];
        for ($i = 0; $i < 3; $i++) {
            for ($j = 0; $j < count($matrix[$i]); $j++) {
                if ($matrix[$i][$j] === 1) {
                    $fisrt = [$i, $j];
                    break 2;
                }
            }
        }

        if (empty($fisrt)) {
            return false;
        }

        if ($matrix[$fisrt[0]+1][$fisrt[1]] === 1 &&
            $matrix[$fisrt[0]+2][$fisrt[1]] === 1 &&
            $matrix[$fisrt[0]+3][$fisrt[1]] === 1 &&
            $matrix[$fisrt[0]+4][$fisrt[1]] === 1) {
            return true;
        }

        return false;
    }

    /**
     * 判定炸弹
     *
     * @return boolean [description]
     */
    private function isBomb($matrix)
    {
        for ($i = 0; $i < count($matrix); $i++) {
            $count = 0;
            for ($j = 0; $j < count($matrix[$i]); $j++) {
                if ($matrix[$i][$j] === 1) $count++;
            }
            if ($count === 4) return true;
        }

        return false;
    }

    /**
     * 判定三条
     *
     * @return boolean false无
     */
    private function isThreefakind($matrix)
    {
        for ($i = 0; $i < count($matrix); $i++) {
            $three = 0;
            for ($j = 0; $j < count($matrix[$i]); $j++) {
                if ($matrix[$i][$j] === 1) {
                    $three++;
                }
            }
            if ($three === 3) return true;
        }

        return false;
    }

    /**
     * 判定对子
     *
     * @return boolean [description]
     */
    private function isPairs($matrix)
    {
        $count = 0;
        for ($i = 0; $i < count($matrix); $i++) {
            $pairs = 0;
            for ($j = 0; $j < count($matrix[$i]); $j++) {
                if ($matrix[$i][$j] === 1) {
                    $pairs++;
                }
            }
            if ($pairs === 2) {
                $count++;
            }
        }

        return $count;
    }

    /**
     * 判定同花
     *
     * @return boolean [description]
     */
    private function isWithColor($matrix)
    {
        $count = 0;
        $index = 0;
        for ($i = 0; $i < count($matrix); $i++) {
            $color = 0;
            for ($j = 0; $j < count($matrix[$i]); $j++) {
                if ($matrix[$i][$j] === 1) {
                    if ($count === 0) {
                        $index = $j;
                        $color++;
                    } elseif ($index === $j) {
                        $color++;
                    }
                }
            }
            if ($color === 1) $count++;
        }

        if ($count === 5 && !$this->isFlush($matrix)) {
            return true;
        }

        return false;
    }

    /**
     * 判定顺子
     *
     * @return boolean [description]
     */
    private function isStraight($matrix)
    {
        $fisrt = [];
        for ($i = 0; $i < 3; $i++) {
            for ($j = 0; $j < count($matrix[$i]); $j++) {
                if ($matrix[$i][$j] === 1) {
                    $fisrt = [$i, $j];
                    break 2;
                }
            }
        }

        if (empty($fisrt)) {
            return false;
        }

        $one = $fisrt[0];
        $count = 0;
        for ($i = $one+1; $i < $one+5; $i++) {
            $straight = 0;
            for ($j = 0; $j < count($matrix[$i]); $j++) {
                if ($matrix[$i][$j] === 1) {
                    $straight++;
                }
            }
            if ($straight === 1) $count++;
        }

        if ($count === 4 && !$this->isFlush($matrix)) {
            return true;
        }

        return false;
    }
}
